#include <queue>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <vector>
#include "API.h"
#include "BaselineRandomWalk.h"
#include "Lottery.h"
#include "Greedy.h"
#include "Greedy2.h"
#include "Greedy3.h"
#include "Greedy4.h"
#include "LearnedModel.h"

using namespace std;

#ifdef _FIX_TELE_

int main(int argc, char* argv[]) {
  int MAX_COST = 10000;

  cout << "Loading Graph" << endl;
  TFIn FIn1("/lfs/1/tmp/saint/twitter/graph.bin");
  PNEGraph Graph = TNEGraph::Load(FIn1);
  cout << "Done" << endl;
  
  API *telapi = new API(Graph);
    
  AlwaysTeleportRandomWalk tel(telapi);
    
  cout << "Crawling using teleport..." << endl;
  tel.crawl(MAX_COST);
  cout << "Done" << endl;
    
  TGnuPlot Gp("NodesExplored", "Nodes Explored");
  Gp.AddPlot(tel.getNodeStatistics(), gpwLines, "Teleport");
  
  Gp.SetXYLabel("Cost", "Nodes found");
  Gp.SavePng();

  Gp = TGnuPlot("EdgesExplored", "Edges Explored");
  Gp.AddPlot(tel.getEdgeStatistics(), gpwLines, "Teleport");
    
  Gp.SetXYLabel("Cost", "Edges found");
  Gp.SavePng();

  return 0;
}

#endif

#ifdef __UNITTEST__

int main(int argc, char* argv[]) {
    //PNEGraph G = TSnap::GenRndGnm<PNEGraph>(10,20);
    
    PNGraph Gtmp = TSnap::GenForestFire(100, 0.35, 0.32);
    //PNEGraph G = TSnap::ConvertGraph<PNEGraph>(Gtmp);
    //TSnap::SaveEdgeList<PNEGraph>(G, "testGraph.bin");
    
    //G = TNEGraph::New();
    //G = TSnap::LoadEdgeList<PNEGraph>("testGraph.bin");
    
    /*
    TIntStrH name;
    for(int i = 0; i < 10; i++) {
        char *tmp = new char[10];
        sprintf(tmp, "v%d", i);
        name.AddDat(i) = tmp;
    }
    TGraphViz::Plot<PNEGraph>(G, gvlDot, "graphPlot.png", "", name);
    */

    API *a = new API(TSnap::ConvertGraph<PNEGraph>(Gtmp));

    LotteryRandomWalk lott(a);
    lott.crawl(100);

    TGnuPlot Gp("NodesExploredlower", "Nodes Explored");
	Gp.AddPlot(lott.getNodeStatistics(), gpwLinesPoints, "Lottery");
    Gp.SetXYLabel("Cost", "Nodes found");
    Gp.SavePng();

    Gp = TGnuPlot("EdgesExploredlower", "Edges Explored");
	Gp.AddPlot(lott.getEdgeStatistics(), gpwLinesPoints, "Lottery");
    Gp.SetXYLabel("Cost", "Edges found");
    Gp.SavePng();
    return 0;
}

#endif

#ifdef _TEST_ALL_

int main(int argc, char* argv[]) {
    const int nodes = 10000;
    const int MAX_COST = nodes*4;
	
    //PNGraph Gtmp = TSnap::GenRndGnm<PNGraph>(nodes, nodes*10);
    PNGraph Gtmp = TSnap::GenForestFire(nodes, 0.35, 0.32);
    //PUNGraph Gtmp = TSnap::GenSmallWorld(nodes, 400, 0.5);
    //PUNGraph Gtmp = TSnap::GenRndDegK(nodes, 10);
    //PUNGraph Gtmp = TSnap::GenRndPowerLaw(nodes, 1.5);
    PNEGraph Graph = TSnap::ConvertGraph<PNEGraph>(Gtmp);
    
    //TSnap::SaveEdgeList<PNEGraph>(Graph, "testGraph.bin");
    //PNEGraph Graph = TSnap::LoadEdgeList<PNEGraph>("greedy4killerGraph.bin");
    TFltPrV upperBound;
    for(int c = 0, v = 0; c < MAX_COST && v <= nodes; c++, v += C)
      upperBound.Add(TFltPr(double(c),double(v)));

    API *greed4api = new API(Graph); 
    greed4api->enableCache();
    
    BaselineRandomWalk base(new API(Graph));
    LotteryRandomWalk lott(new API(Graph));
    AlwaysTeleportRandomWalk tel(new API(Graph));
    Greedy greed(new API(Graph));
    Greedy2 greed2(new API(Graph));
    Greedy3 greed3(new API(Graph));
    Greedy4 greed4(greed4api);
    LearnedModel lm(new API(Graph));
    lm.learnParams();
    //lm.saveParams("param10000d.bin");
    //lm.loadParams("param1000.bin");

    cout << "Crawling using baseline random walk..." << endl;
    base.crawl(MAX_COST);
    cout << "Done" << endl;
    cout << "Crawling using lottery..." << endl;
    lott.crawl(MAX_COST);
    cout << "Done" << endl;
    cout << "Crawling using teleport..." << endl;
    tel.crawl(MAX_COST);
    cout << "Done" << endl;
    cout << "Crawling using greedy..." << endl;
    greed.crawl(MAX_COST);
    cout << "Done" << endl;
    cout << "Crawling using greedy2..." << endl;
    greed2.crawl(MAX_COST);
    cout << "Done" << endl;
    cout << "Crawling using greedy3..." << endl;
    greed3.crawl(MAX_COST);
    cout << "Done" << endl;
    cout << "Crawling using greedy4..." << endl;
    greed4.crawl(MAX_COST);
    cout << "Done" << endl;
    cout << "Crawling using lm..." << endl;
    lm.crawl(MAX_COST);
    cout << "Done" << endl;

    TGnuPlot Gp("NodesExplored", "Nodes Explored");
    Gp.AddPlot(tel.getNodeStatistics(), gpwLines, "Teleport");
    Gp.AddPlot(base.getNodeStatistics(), gpwLines, "Random Walk");
    Gp.AddPlot(greed.getNodeStatistics(), gpwLines, "Greedy");
    Gp.AddPlot(lott.getNodeStatistics(), gpwLines, "Lottery");
    Gp.AddPlot(greed2.getNodeStatistics(), gpwLines, "Greedy2");
    Gp.AddPlot(greed3.getNodeStatistics(), gpwLines, "Greedy3");
    Gp.AddPlot(greed4.getNodeStatistics(), gpwLines, "Greedy4");
    Gp.AddPlot(lm.getNodeStatistics(), gpwLines, "lm");
    Gp.AddPlot(upperBound, gpwLines, "UpperBound");
    
    Gp.SetXYLabel("Cost", "Nodes found");
    Gp.SavePng();

    Gp = TGnuPlot("EdgesExplored", "Edges Explored");
    Gp.AddPlot(tel.getEdgeStatistics(), gpwLines, "Teleport");
    Gp.AddPlot(base.getEdgeStatistics(), gpwLines, "Random Walk");
    Gp.AddPlot(greed.getEdgeStatistics(), gpwLines, "Greedy");
    Gp.AddPlot(lott.getEdgeStatistics(), gpwLines, "Lottery");
    Gp.AddPlot(greed2.getEdgeStatistics(), gpwLines, "Greedy2");
    Gp.AddPlot(greed3.getEdgeStatistics(), gpwLines, "Greedy3");    
    Gp.AddPlot(greed4.getEdgeStatistics(), gpwLines, "Greedy4");    
    Gp.AddPlot(lm.getEdgeStatistics(), gpwLines, "lm");
    Gp.AddPlot(upperBound, gpwLines, "UpperBound");

    Gp.SetXYLabel("Cost", "Edges found");
    Gp.SavePng();

    return 0;
}

#endif
